/**
 *   Copyright 2014 Royce Remulla
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package cjcast.y2015.problem;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Terms: <br/>
 * Good(working)/Bad(broken) led state. On/Off
 * 
 * @author royce.com@gmail.com
 */
public enum Digit {


    //    0X7E, //1111110 0 126
    //    0X30, //0110000 1 48
    //    0X6D, //1101101 2 109
    //    0X79, //1111001 3 121
    //    0X33, //0110011 4 51
    //    0X5B, //1011011 5 91
    //    0X5F, //1011111 6 95
    //    0X70, //1110000 7 112
    //    0X7F, //1111111 8 127
    //    0X7B }; //1111011 9 123

    /** */
    Zero(0x7E), One(0x30), Two(0x6D), Three(0x79),
    /** */
    Four(0X33), Five(0x5B), Six(0x5F), Seven(0x70),
    /** */
    Eight(0X7F), Nine(0x7B);

    /** sl4j logger instance. */
    private static final Logger LOGGER = LoggerFactory.getLogger(Digit.class);


    /** */
    private final byte digitLED;

    Digit(final int pLedFlag) {
        digitLED = (byte) pLedFlag;
    }

    /** */
    private static Digit[] orderArr = new Digit[] {
            Zero,
            One,
            Two,
            Three,
            Four,
            Five,
            Six,
            Seven,
            Eight,
            Nine };

    byte toByte()
    {
        return digitLED;
    }

    static Digit fromValue(final int ordinal)
    {
        assert ordinal >= 0 && ordinal < values().length;
        return orderArr[ordinal];
    }

    /**
     * Return true of the given led combination is a possibly equivalent.
     */
    boolean accept(final byte actualLED, final byte goodLED)
    {
        final boolean same = digitLED == actualLED;
        final byte unused = (byte) ~actualLED;

        final boolean hasUnused = (unused & digitLED & goodLED) != 0;
        final boolean spill = (~digitLED & actualLED) != 0;

        return same || !spill && !hasUnused;
    }

    /** Returns the LED string with the supplied bad LEDs. */
    @SuppressWarnings({
            "PMD.UseVarargs",
            "PMD.OnlyOneReturn" /* Two only. */})
    byte breakLed(final byte goodLED)
    {
        assert goodLED <= LEDState.LED_ALL_ON && goodLED >= 0;
        return (byte) (digitLED & goodLED);
    }

}
